import java.util.HashMap;
import java.util.Map;

import util.ConfidenceInterval;

import eduni.simjava.Sim_system;
import entities.Lan;
import entities.Measurable;
import entities.Router;
import entities.Source;

public class RouterSimulator {

	public static void main(String[] args) throws InterruptedException {

		boolean interval = false;

		String[] entities = { "Router", "Lan One", "Lan Two" };
		
		Map<String, ConfidenceInterval> map = new HashMap<String, ConfidenceInterval>();
		
		for (String s : entities) {
			map.put(s + " N", new ConfidenceInterval(ConfidenceInterval.NOVENTA));
			map.put(s + " S", new ConfidenceInterval(ConfidenceInterval.NOVENTA));
			map.put(s + " R", new ConfidenceInterval(ConfidenceInterval.NOVENTA));
			map.put(s + " U", new ConfidenceInterval(ConfidenceInterval.NOVENTA));
			map.put(s + " Q", new ConfidenceInterval(ConfidenceInterval.NOVENTA));
		}
		
		int experiments = 0;
		
		while (!interval) {

			Sim_system.initialise();
			
			// cria as fontes de cada classe de pacotes
			// o parametro primeiro eh a quantidade de pacotes por segundo
			// o segundo eh o tamanho do pacote gerado em bits
			Sim_system.add(new Source("Source Class One", 90000, 250));
			Sim_system.add(new Source("Source Class Two", 90000, 750));
			
			// cria o roteador
			// o primeiro parametro eh a quantidade de bits por segundo
			// o segundo parametro eh a probabilidade de a saida ser lan 01.
			Sim_system.add(new Router("Router", 97000000, 0.5));
			
			// cria as lans
			// o primeiro parametro eh a quantidade de bits por segundo
			Sim_system.add(new Lan("Lan One", 100000000));
			Sim_system.add(new Lan("Lan Two", 100000000));

			// linka as portas
			Sim_system.link_ports("Source Class One", "out", "Router", "in1");
			Sim_system.link_ports("Source Class Two", "out", "Router", "in2");

			Sim_system.link_ports("Router", "out1", "Lan One", "in");
			Sim_system.link_ports("Router", "out2", "Lan Two", "in");

			Sim_system.run();
			
			experiments++;
			
			for (String s : entities) {
				Measurable m = (Measurable) Sim_system.get_entity(s);
				
				ConfidenceInterval cN = map.get(s + " N");
				ConfidenceInterval cS = map.get(s + " S");
				ConfidenceInterval cR = map.get(s + " R");
				ConfidenceInterval cU = map.get(s + " U");
				ConfidenceInterval cQ = map.get(s + " Q");
				
				cN.addValue(m.meanN());
				cS.addValue(m.getS());
				cR.addValue(m.getR());
				cU.addValue(m.getU());
				cQ.addValue(m.meanQ());
				
			}
			
			if (experiments >= 2) {
				double max = 0;

				for (String s : entities) {
					ConfidenceInterval cN = map.get(s + " N");
					ConfidenceInterval cS = map.get(s + " S");
					ConfidenceInterval cR = map.get(s + " R");
					ConfidenceInterval cU = map.get(s + " U");
					//ConfidenceInterval cQ = map.get(s + " Q");
					
					max = Math.max(max, cN.getRelativeWidth());
					max = Math.max(max, cS.getRelativeWidth());
					max = Math.max(max, cR.getRelativeWidth());
					max = Math.max(max, cU.getRelativeWidth());
					//max = Math.max(max, cQ.getRelativeWidth());
				}
				
				interval = max < 0.05;
			}

		}
		
		for (String s : entities) {
			System.out.println("Entidade: " + s);
			
			ConfidenceInterval cN = map.get(s + " N");
			ConfidenceInterval cS = map.get(s + " S");
			ConfidenceInterval cR = map.get(s + " R");
			ConfidenceInterval cU = map.get(s + " U");
			ConfidenceInterval cQ = map.get(s + " Q");
			
			System.out.println("Mean N: " + cN);
			System.out.println("Service Time: " + cS);
			System.out.println("Response Time: " + cR);
			System.out.println("Utilization: " + cU);
			System.out.println("Mean Queue Size: " + cQ);
		}
		
		System.exit(0);
	}

}
